package com.xqboss.common.utils.sms;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.xqboss.common.config.XQBossConfig;
import com.xqboss.common.constant.CacheConstants;
import com.xqboss.common.constant.Constants;
import com.xqboss.common.core.redis.RedisCache;
import com.xqboss.common.enums.MessageSendEnum;
import com.xqboss.common.exception.user.CaptchaException;
import com.xqboss.common.exception.user.CaptchaExpireException;
import com.xqboss.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 短信工具类
 *
 * @author Administrator
 */
@Slf4j
public class SmsUtil {

    private static RedisCache redisCache = SpringUtils.getBean(RedisCache.class);


    /**
     * 验证码模版，获取验证码，验证码：${code}，该验证码5分钟内有效，请勿泄漏于他人！
     */
//    static final String TEMPLATE1 = "SMS_199202322";
    static final String TEMPLATE1 = "SMS_228230005";

    /**
     * 发送验证码
     *
     * @param phone   手机号码
     * @param msgCode 验证码
     * @return 返回true
     */
    public static boolean sendMsg(String phone, String msgCode) {
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(msgCode)) {
            return false;
        }
        IAcsClient client = SmsClient.getClient();
        CommonRequest request = SmsClient.getCommonRequest();
        request.setSysAction("SendSms");
        request.putQueryParameter("PhoneNumbers", phone);
        request.putQueryParameter("TemplateCode", TEMPLATE1);
        /**
         * 组装短信模板参数
         * Map<String,Object> param = new HashMap<>();
         * param.put("code", code);
         * Gson gson = new Gson();
         * String json = gson.toJson(param);
         */
        request.putQueryParameter("TemplateParam", "{\"code\":\"" + msgCode + "\"}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            JSONObject jsonObject = JSONObject.parseObject(response.getData());
            log.info("手机号：{}, 阿里发送验证码返回：{}", phone, jsonObject.toJSONString());
            String status = jsonObject.getString("Code");
            if ("OK".equals(status)) {
                return true;
            }
        } catch (ClientException e) {
            log.error("ErrorCode=" + e.getErrCode());
            log.error("ErrorMessage=" + e.getErrMsg());
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 设置验证码
     *
     * @param cacheKey
     * @param smsCode
     */
    public static void setSmsCode(String cacheKey, String smsCode) {
        redisCache.setCacheObject(cacheKey, smsCode, Constants.CAPTCHA_EXPIRATION_SECOND, TimeUnit.SECONDS);
    }

    /**
     * 获取验证码
     *
     * @param cacheKey
     */
    public static String getSmsCode(String cacheKey) {
        return redisCache.getCacheObject(cacheKey);
    }

    /**
     * 获取验证码保存了多久
     *
     * @param cacheKey
     * @return
     */
    public static long getSmsCodeLessExpire(String cacheKey) {
        return Constants.CAPTCHA_EXPIRATION_SECOND - redisCache.getExpireforSeconds(cacheKey);
    }

    /**
     * 设置cacheKey
     *
     * @param mobile
     * @param type
     * @return
     */
    public static String setCacheKey(String mobile, String type) {
        String cacheKey = "";
        switch (MessageSendEnum.resolve(type)) {
            case LOGIN:
                cacheKey = Constants.LOGINS + CacheConstants.CAPTCHA_CODE_KEY + mobile;
                break;
            case REGISTER:
                cacheKey = Constants.REGISTER + CacheConstants.CAPTCHA_CODE_KEY + mobile;
                break;
            case FORGET_PASSWORD:
                cacheKey = CacheConstants.CAPTCHA_CODE_KEY + mobile;
                break;
            case GENERAL_CODE:
                cacheKey = Constants.GENERAL + CacheConstants.CAPTCHA_CODE_KEY + mobile;
                break;
        }
        return cacheKey;
    }

    /**
     * 校验验证码
     */
    public static void validateCaptcha(String username, String code, String businessType) {
        String verifyKey;
        if (StrUtil.isBlank(username) && StrUtil.isBlank(businessType)) { //身份认证修改支付密码 code 为身份验证码 uuid字符串
            verifyKey = CacheConstants.AUTHENTICATION_KEY + code;
        } else {
            verifyKey = setCacheKey(username, businessType);
        }
        String captcha = redisCache.getCacheObject(verifyKey);

        if (captcha == null) {
            throw new CaptchaExpireException();
        }
        if (!code.equalsIgnoreCase(captcha)) {
            //验证码错误，记录错误次数
            int maxRetryCount = XQBossConfig.getMaxRetryCount();
            Integer retryCount = redisCache.getCacheObject(CacheConstants.SMS_ERR_CNT + username);
            if(Objects.isNull(retryCount)){
                retryCount = 0;
            }
            if(retryCount + 1 >= maxRetryCount){
                // 清除验证码及错误次数
                redisCache.deleteObject(CacheConstants.SMS_ERR_CNT + username);
                redisCache.deleteObject(verifyKey);
                throw new CaptchaExpireException();
            }else{
                long expireSecond = redisCache.getExpireforSeconds(verifyKey);
                if(expireSecond > 0){
                    redisCache.setCacheObject(CacheConstants.SMS_ERR_CNT + username, retryCount + 1, (int) expireSecond, TimeUnit.SECONDS);
                }else{
                    // 防止刚好过期问题
                    redisCache.deleteObject(CacheConstants.SMS_ERR_CNT + username);
                }
            }
            throw new CaptchaException();
        }
        redisCache.deleteObject(verifyKey);
    }

}
